package com.javaweb.web.controller;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.javaweb.annotation.token.TokenDataAnnotation;
import com.javaweb.annotation.url.ControllerMethod;
import com.javaweb.base.BaseResponseResult;
import com.javaweb.base.BaseService;
import com.javaweb.base.BaseSystemMemory;
import com.javaweb.base.po.Interfaces;
import com.javaweb.base.po.Module;
import com.javaweb.constant.ApiCommonConstant.ModuleConstant;
import com.javaweb.constant.CommonConstant;
import com.javaweb.db.query.QueryWapper;
import com.javaweb.enums.AuthEnum;
import com.javaweb.enums.HttpCodeEnum;
import com.javaweb.util.core.StringUtil;
import com.javaweb.util.entity.Page;
import com.javaweb.web.eo.TokenData;
import com.javaweb.web.eo.module.ModuleAddRequest;
import com.javaweb.web.eo.module.ModuleListRequest;
import com.javaweb.web.eo.module.ModuleModifyRequest;

/**
 * 登录且需要权限才可访问的模块管理模块
 * <p>
 * 该模块主要提供模块管理相关的接口
 * 
 * @author tank2140896
 */
@RestController
@RequestMapping(ModuleConstant.WEB_MODULE_PREFIX)
public class ModuleController extends BaseService {
    
	/**
	 * 获取模块ID和模块名称列表接口
	 * 
	 * @param moduleType 模块类型
	 * @return BaseResponseResult 接口通用返回参数
	 */
    @GetMapping(ModuleConstant.MODULE_GET_MODULE_ID_AND_NAME_LIST)
    @ControllerMethod(interfaceName="获取模块ID和模块名称列表接口",auth=AuthEnum.PERMISSION)
    public BaseResponseResult getModuleIdAndNameList(@PathVariable(name="moduleType",required=false) String moduleType) {
        return getBaseResponseResult(HttpCodeEnum.SUCCESS,"module.getModuleIdAndNameList.success",moduleService.getModuleIdAndNameList(moduleType));
    }
	
	/**
	 * 新增模块接口
	 * <p>
	 * 实践建议：
	 * 1、目录：模块的上级ID可选（有上级ID就是子目录）也可不选（没有上级ID就是根目录），页面URL和API的URL都是不需要的；
	 * 2、菜单：模块的上级ID必选（所有目录，即moduleType=1），需要页面的URL；
	 * 3、功能：模块的上级ID必选（所有菜单，即moduleType=2），需要API的URL
	 * 
	 * @param moduleAddRequest 模块新增请求参数
	 * @param tokenData tokenData
	 * @return BaseResponseResult 接口通用返回参数
	 */
    @PostMapping(ModuleConstant.MODULE_ADD)
	@ControllerMethod(interfaceName="新增模块接口",auth=AuthEnum.PERMISSION)
	public BaseResponseResult moduleAdd(@RequestBody @Validated ModuleAddRequest moduleAddRequest,@TokenDataAnnotation TokenData tokenData){
		/** 新增模块-字段唯一性校验 start */
		List<QueryWapper<Module>> queryWappers = List.of(
			new QueryWapper<Module>().eq(Module::getModuleName,moduleAddRequest.getModuleName()).eq(Module::getDelFlag,0),
			new QueryWapper<Module>().eq(Module::getAlias,moduleAddRequest.getAlias()).eq(Module::getDelFlag,0)
		);
		List<String> messages = List.of("validated.module.moduleName.repeat","validated.module.alias.repeat");
		validateService.columnUniqueCheck(moduleDao,queryWappers,messages);
		/** 新增模块-字段唯一性校验 end */
    	if((moduleAddRequest.getModuleType()==3)&&(Objects.equals(moduleAddRequest.getPlatformName(),environment.getProperty("spring.application.name")))){//功能且同一个平台
			if(StringUtil.isEmpty(moduleAddRequest.getApiUrl())){
				return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"interfaces.notExist.fail");
			}
			Map<String,Interfaces> interfacesUrlMap = BaseSystemMemory.interfacesMap;
			boolean allMatch = Stream.of(moduleAddRequest.getApiUrl().split(CommonConstant.COMMA)).allMatch(e->interfacesUrlMap.get(e)!=null);
			if(!allMatch){
				return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"interfaces.notExist.fail");
			}
		}
		moduleService.moduleAdd(tokenData.getUser(),moduleAddRequest);
		return getBaseResponseResult(HttpCodeEnum.SUCCESS,"module.add.success");
	}
	
	/**
	 * 查询模块接口
	 * 
	 * @param moduleListRequest 模块列表请求参数
	 * @return BaseResponseResult 接口通用返回参数
	 */
	@PostMapping(ModuleConstant.MODULE_LIST)
	@ControllerMethod(interfaceName="查询模块接口",auth=AuthEnum.PERMISSION)
	public BaseResponseResult moduleList(@RequestBody ModuleListRequest moduleListRequest){
		Page page = moduleService.moduleList(moduleListRequest);
		return getBaseResponseResult(HttpCodeEnum.SUCCESS,"module.list.success",page);
	}
	
	/**
	 * 修改模块接口
	 * <p>
	 * 实践建议：
     * 1、不能自己关联自己，即将pid设置为自己；
     * 2、判断是否有下级关联；
     * 3、在有下级关联的情况下（操作（按钮）永远排除在外），升降级判断（即非同级操作）：
     *   3.1、当前权限若是目录不能向下降级为菜单或操作（按钮）；
     *   3.2、当前权限若是菜单既不能向上升级也不能向下降级
	 * 
	 * @param moduleModifyRequest 模块修改请求参数
	 * @param tokenData tokenData
	 * @return BaseResponseResult 接口通用返回参数
	 */
	@PutMapping(ModuleConstant.MODULE_MODIFY)
	@ControllerMethod(interfaceName="修改模块接口",auth=AuthEnum.PERMISSION)
	public BaseResponseResult moduleModify(@RequestBody @Validated ModuleModifyRequest moduleModifyRequest,@TokenDataAnnotation TokenData tokenData){
		Module originModule = moduleService.moduleDetail(moduleModifyRequest.getModuleId());
		if(originModule==null){
			return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"validated.module.modify.notExist");
		}
		/** 修改模块-字段唯一性校验 start */
		List<QueryWapper<Module>> queryWappers = List.of(
			new QueryWapper<Module>().eq(Module::getModuleName,moduleModifyRequest.getModuleName()).eq(Module::getDelFlag,0).neq(Module::getModuleId,moduleModifyRequest.getModuleId()),
			new QueryWapper<Module>().eq(Module::getAlias,moduleModifyRequest.getAlias()).eq(Module::getDelFlag,0).neq(Module::getModuleId,moduleModifyRequest.getModuleId())
		);
		List<String> messages = List.of("validated.module.moduleName.repeat","validated.module.alias.repeat");
		validateService.columnUniqueCheck(moduleDao,queryWappers,messages);
		/** 修改模块-字段唯一性校验 end */
		if(originModule.getModuleId().equals(moduleModifyRequest.getParentId())){//不能自己关联自己
			return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"module.modify.fail");
		}
		List<Module> moduleList = moduleService.getModuleByParentId(moduleModifyRequest.getModuleId());
		if(moduleList!=null&&moduleList.size()>0){//判断是否有下级关联
			if(originModule.getModuleType()!=moduleModifyRequest.getModuleType()){//判断是否是同级操作
				if(originModule.getModuleType()<moduleModifyRequest.getModuleType()){//判断是否是降级操作
					return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"module.modify.fail");
				}else{
					if(originModule.getModuleType()!=1){//若是升级操作，只能原来是目录的升目录
						return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"module.modify.fail");
					}
				}
			}
		}
		if((moduleModifyRequest.getModuleType()==3)&&(Objects.equals(moduleModifyRequest.getPlatformName(),environment.getProperty("spring.application.name")))){//功能且同一个平台
			if(StringUtil.isEmpty(moduleModifyRequest.getApiUrl())){
				return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"interfaces.notExist.fail");
			}
			Map<String,Interfaces> interfacesUrlMap = BaseSystemMemory.interfacesMap;
			boolean allMatch = Stream.of(moduleModifyRequest.getApiUrl().split(CommonConstant.COMMA)).allMatch(e->interfacesUrlMap.get(e)!=null);
			if(!allMatch){
				return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"interfaces.notExist.fail");
			}
		}
		moduleService.moduleModify(tokenData.getUser(),moduleModifyRequest);
		return getBaseResponseResult(HttpCodeEnum.SUCCESS,"module.modify.success");
	}
	
	/**
	 * 模块详情接口
	 * 
	 * @param moduleId 模块ID
	 * @return BaseResponseResult 接口通用返回参数
	 */
	@GetMapping(ModuleConstant.MODULE_DETAIL)
	@ControllerMethod(interfaceName="模块详情接口",auth=AuthEnum.PERMISSION)
	public BaseResponseResult moduleDetail(@PathVariable(name="moduleId",required=true) String moduleId){
		Module module = moduleService.moduleDetail(moduleId);
		return getBaseResponseResult(HttpCodeEnum.SUCCESS,"module.detail.success",module);
	}
	
	/**
	 * 删除模块接口（支持批量删除，用逗号隔开）
	 * 
	 * @param moduleId 模块ID
	 * @return BaseResponseResult 接口通用返回参数
	 */
	@DeleteMapping(ModuleConstant.MODULE_DELETE)
	@ControllerMethod(interfaceName="删除模块接口（支持批量删除，用逗号隔开）",auth=AuthEnum.PERMISSION)
	public BaseResponseResult moduleDelete(@PathVariable(name="moduleId",required=true) String moduleId){
		String moduleIds[] = moduleId.split(CommonConstant.COMMA);
		for(String eachModuleId:moduleIds){
			//删除权限，只需要判断当前权限有没有下级关联，没有即可删除
			Module module = moduleService.moduleDetail(eachModuleId);
			if(module.getModuleType()!=3){//非功能需要进一步判断才能确定是否可以删除
				List<Module> moduleList = moduleService.getModuleByParentId(module.getModuleId());
				if(!CollectionUtils.isEmpty(moduleList)) {//当删除目录或菜单时，若有下级关联，则不允许删除
					return getBaseResponseResult(HttpCodeEnum.VALIDATE_ERROR,"module.delete.fail");
				}
			}
		}
		moduleService.moduleDelete(moduleIds);
		return getBaseResponseResult(HttpCodeEnum.SUCCESS,"module.delete.success");
	}
	
}
